package com.jy.rhin.application.cda;

import com.jy.api.patient.PatientAPI;
import com.jy.api.patient.dto.BingRenXXDto;
import com.jy.common.StringUtil;
import com.jy.framework.base.utils.Serializer;
import com.jy.rhin.application.document.DocumentBizService;
import com.jy.rhin.domain.document.validation.IDocumentValidataResultService;
import com.jy.rhin.facade.cda.dto.ChanHouFSDto;
import com.jy.rhin.facade.cda.dto.ReqDto;
import com.jy.rhin.facade.cda.dto.WenDangSCDto;
import com.jy.rhin.infra.repo.document.validation.query.DocumentValidateQueryHandler;
import com.jy.rhin.parse.CDAParser;
import com.jy.rhin.sdk.dto.document.query.DocumentValidateResultDetailDto;
import com.jy.rhin.sdk.dto.document.query.DocumentValidateResultDto;
import com.jy.rhin.sdk.dto.document.query.DocumentValidationFileRespDto;
import com.jy.rhin.valid.CdaValidator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class CdaApplication {
    @Autowired
    private IDocumentValidataResultService documentValidataResultServvice;
    @Autowired
    private MenZhenZhaiYaoApplication menZhenZhaiYaoApplication;
    @Autowired
    private YuFangJZApplication yuFangJZApplication;
    @Autowired
    private ChanHouFSApplication chanHouFSApplication;
    @Autowired
    private ChanHouJCApplication chanHouJCApplication;
    @Autowired
    private ChanQianSFApplication chanQianSFApplication;
    @Autowired
    private ChanQianSCSFApplication chanQianSCSFApplication;
    @Autowired
    private HuiZhenJLApplication huiZhenJLApplication;
    @Autowired
    private GeRenJBJKXXApplication geRenJBJKXXApplication;
    @Autowired
    private XinShengErFSApplication xinShengErFSApplication;
    @Autowired
    private ChuShengYXZMApplication chuShengYXZMApplication;
    @Autowired
    private GaoXueYSFApplication gaoXueYSFApplication;
    @Autowired
    private TangNiaoBSFApplication tangNiaoBSFApplication;
    @Autowired
    private ZhongXingJSBDJApplication zhongXingJSBDJApplication;
    @Autowired
    private ZhongXingJSBSFApplication zhongXingJSBSFApplication;
    @Autowired
    private JianKangTJApplication jianKangTJApplication;
    @Autowired
    private ZhuYuanZhaiYaoApplication zhuYuanZhaiYaoApplication;
    @Autowired
    private SiWangYXZMApplication siWangYXZMApplication;
    @Autowired
    private ErTongJKTJApplication erTongJKTJApplication;
    @Autowired
    private ChuanRanBBGApplication chuanRanBBGApplication;
    @Autowired
    private PatientAPI patientAPI;
    @Autowired
    private ZhuanZhenJLApplication zhuanZhenJLApplication;
//    @Autowired
//    private ReservationCenterAPI reservationCenterAPI;
//    @Autowired
//    private ConsultationAPI consultationAPI;
    @Resource
    DocumentBizService documentBizService;

    @Autowired
    private DocumentValidateQueryHandler documentValidateQueryHandler;

    public void validateAndRegister(String xml, String appId, String eid) throws Exception {
        // 校验
        CdaValidator cdaValidator = new CdaValidator();
        cdaValidator.validate(xml);
        Map<String, String> exceptionMap = cdaValidator.getExceptionMap();
        int success = 0;
        int fail = 0;
        List<DocumentValidateResultDetailDto> list = new ArrayList<DocumentValidateResultDetailDto>();
        for (Map.Entry<String, String> entry : exceptionMap.entrySet()) {
            DocumentValidateResultDetailDto d = new DocumentValidateResultDetailDto();
            d.setContent(entry.getKey() + " " + entry.getValue());
            if (entry.getValue().contains("成功")) {
                d.setDetailResult("1");
                success++;
            } else {
                d.setDetailResult("0");
                fail++;
            }
            list.add(d);
        }
        // 解析
        CDAParser cdaParser = new CDAParser(xml);
        com.jy.rhin.sdk.dto.document.cda.ClinicalDocumentData fs = Serializer.deserialize(
                Serializer.serialize(cdaParser.parse()), com.jy.rhin.sdk.dto.document.cda.ClinicalDocumentData.class);
        fs.setContent(xml.getBytes("UTF-8"));
        fs.setAppid(appId);
        fs.setEid(eid);
        DocumentValidateResultDto d = new DocumentValidateResultDto();
        d.setValidateResult(fail == 0 ? "1" : "0");
        d.setDocumentId(fs.getId());
        // 调用webservice接口注册存储
        if ("1".equals(d.getValidateResult())) {
            try {
                documentBizService.register(fs);
                d.setUploadResult("1");
            } catch (Exception e) {
                d.setUploadResult("0");
                d.setFailReason(ExceptionUtils.getMessage(e));
            }
        } else {
            d.setUploadResult("0");
            d.setFailReason("校验未通过");
        }

        d.setDocumentType(fs.getTitle());
        d.setDocumentCreateTime(new Date());
        d.setActivateNum(fail + success);
        d.setSuccessNum(success);
        d.setFailNum(fail);
        d.setUploadUrl("lb://rhin-aggr-service/ws/DocumentStorage");
        d.setUploadTime(new Date());
        d.setDetails(list);
        d.setXml(xml);
        d.setBingRenXM(fs.getPatientRole().getPatient().getName());
        d.setZhengJianHM(fs.getPatientRole().getPatient().getId());
        documentValidataResultServvice.saveResult(d);
    }


    public DocumentValidateResultDto validate(String xml) throws Exception {
        // 校验
        CdaValidator cdaValidator = new CdaValidator();
        cdaValidator.validate(xml);
        Map<String, String> exceptionMap = cdaValidator.getExceptionMap();
        int success = 0;
        int fail = 0;
        List<DocumentValidateResultDetailDto> list = new ArrayList<DocumentValidateResultDetailDto>();
        for (Map.Entry<String, String> entry : exceptionMap.entrySet()) {
            DocumentValidateResultDetailDto d = new DocumentValidateResultDetailDto();
            d.setContent(entry.getKey() + " " + entry.getValue());
            if (entry.getValue().contains("成功")) {
                d.setDetailResult("1");
                success++;
            } else {
                d.setDetailResult("0");
                fail++;
            }
            list.add(d);
        }
        // 解析
        CDAParser cdaParser = new CDAParser(xml);
        com.jy.rhin.sdk.dto.document.cda.ClinicalDocumentData fs = Serializer.deserialize(
                Serializer.serialize(cdaParser.parse()), com.jy.rhin.sdk.dto.document.cda.ClinicalDocumentData.class);
        fs.setContent(xml.getBytes("UTF-8"));
        DocumentValidateResultDto d = new DocumentValidateResultDto();
        d.setValidateResult(fail == 0 ? "1" : "0");
        d.setUploadResult(fail == 0 ? "1" : "0");
        d.setDocumentId(fs.getId());
        d.setDocumentType(fs.getTitle());
        d.setDocumentCreateTime(new Date());
        d.setActivateNum(fail + success);
        d.setSuccessNum(success);
        d.setFailNum(fail);
        d.setUploadTime(new Date());
        d.setDetails(list);
        DocumentValidationFileRespDto dto = new DocumentValidationFileRespDto();
        dto.setFileType(fs.getTitle());
        d.setRuleNum(documentValidateQueryHandler.getRuleNumByFileType(dto.getFileType()));

        return d;
    }

    public void createByLX(List<WenDangSCDto> wenDangSCDtos) throws Exception {
        String xml = null;
        Map<String, String> binRenXXEidMap = new HashMap<>();
        for (WenDangSCDto wenDangSCDto : wenDangSCDtos) {
//            if ("zhuanZhen".equals(wenDangSCDto.getTableName())) {
//                zhuanZhenSet(wenDangSCDto);
//                continue;
//            }
//            if ("huiZhen".equals(wenDangSCDto.getTableName())) {
//                huiZhenSet(wenDangSCDto);
//                continue;
//            }
            String eid = binRenXXEidMap.get(wenDangSCDto.getPatientId());
            if (eid == null) {
                BingRenXXDto bingRenXXDto = patientAPI.findById(wenDangSCDto.getPatientId());
                if (bingRenXXDto == null) {
                    continue;
                }
                eid = bingRenXXDto.getEid();
                binRenXXEidMap.put(wenDangSCDto.getPatientId(), eid);
            }
            ReqDto reqDto;
            switch (wenDangSCDto.getTableName()) {
                case "YL_MENZHENJZJL": //门诊住院摘要
                    reqDto = getReqDto(wenDangSCDto, eid);
                    xml = menZhenZhaiYaoApplication.create(reqDto);
                    break;
                case "JB_YUFANGJZK": //预防接种报告
                    xml = yuFangJZApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "FY_CHANHOUCFFS": //产后访视
                    ChanHouFSDto chanHouFSDto = getChanHouFSDto(wenDangSCDto, eid);
                    xml = chanHouFSApplication.create(chanHouFSDto);
                    break;
                case "FY_CHANHOU42TJKJC": //产后42天健康体检
                    xml = chanHouJCApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "FY_CHANQIANSFJL": //产前随访服务
                    xml = chanQianSFApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "FY_SHOUCISFJL": //首次产前随访服务
                    xml = chanQianSCSFApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_HUIZHENJL": //会诊记录 调用外部应用
                    xml = huiZhenJLApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_ZHUANZHENJL": //转诊（院）记录 调用外部应用
                    xml = zhuanZhenJLApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_GERENJKDASY": //个人基本健康信息登记  弃用
                case "JK_GERENJBXX":  //个人基本健康信息登记  最多只会有一条
                    xml = geRenJBJKXXApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "FY_XINSHENGEJTFS": //新生儿家庭访视
                    xml = xinShengErFSApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "FY_CHUSHENGYXZM": //出生医学证明
                    xml = chuShengYXZMApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_GAOXUEYSFDJ": //高血压患者随访服务
                    xml = gaoXueYSFApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_TANGNIAOBSFDJ": //2型糖尿病患者随访服务
                    xml = tangNiaoBSFApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_JINGSHENBDJ": //重性精神疾病患者个人信息登记
                    xml = zhongXingJSBDJApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_JINGSHENBSFJL": //重性精神病患者随访服务
                    xml = zhongXingJSBSFApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "JK_TIJIANJBXX": //成人健康体检   难度高
                    xml = jianKangTJApplication.create(wenDangSCDto.getYiLiaoJGDM(), wenDangSCDto.getZiDuan());
                    break;
                case "YL_ZHUYUANJZJL": //住院摘要
                    reqDto = getReqDto(wenDangSCDto, eid);
                    xml = zhuYuanZhaiYaoApplication.create(reqDto);
                    break;
                case "JB_SIWANGYXZM": //死亡医学证明,最多只有一条
                    xml = siWangYXZMApplication.create(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM());
                    break;
                case "FY_YISUIETJKJC": //儿童健康体检 弃用
                case "FY_LIANGSUIETJKJC"://儿童健康体检 弃用
                case "FY_SANSUIETJKJC": //儿童健康体检
                    xml = erTongJKTJApplication.createErTongJKTJ(wenDangSCDto.getZiDuan(), wenDangSCDto.getYiLiaoJGDM(), wenDangSCDto.getTableName());
                    break;
                case "JB_CHUANRANBBK":
                    xml = chuanRanBBGApplication.create(wenDangSCDto.getYiLiaoJGDM(), wenDangSCDto.getZiDuan());
                    break;
                default:
                    log.error("没有对应的类型，传参为: {}", wenDangSCDto.getTableName());
                    break;
            }
            if (StringUtil.isNullOrEmpty(xml)) {
                log.debug("表名为:{}, xml为空", wenDangSCDto.getTableName());
                return;
            }
            log.debug("表名为:{}, xml为:{}", wenDangSCDto.getTableName(), xml);
            validateAndRegister(xml, wenDangSCDto.getAppId(), eid);
        }

//        return xml;
    }

    private ReqDto getReqDto(WenDangSCDto wenDangSCDto, String eid) {
        ReqDto reqDto = new ReqDto();
        reqDto.setAppid(wenDangSCDto.getAppId());
        reqDto.setEid(eid);
        reqDto.setYuanQuID(wenDangSCDto.getYuanQuId());
        reqDto.setYiLiaoJGDM(wenDangSCDto.getYiLiaoJGDM());
        reqDto.setJiuZhenLSH(wenDangSCDto.getZiDuan());
        return reqDto;
    }

    private ChanHouFSDto getChanHouFSDto(WenDangSCDto wenDangSCDto, String eid) {
        ChanHouFSDto chanHouFSDto = new ChanHouFSDto();
        chanHouFSDto.setAppid(wenDangSCDto.getAppId());
        chanHouFSDto.setEid(eid);
        chanHouFSDto.setFUWUJGBH(wenDangSCDto.getYiLiaoJGDM());
        chanHouFSDto.setCHANHOUFSJLBH(wenDangSCDto.getZiDuan());
        return chanHouFSDto;
    }


//    private void zhuanZhenSet(WenDangSCDto wenDangSCDto) throws Exception {
//        List<Long> ids = JSONArray.parseArray(wenDangSCDto.getZiDuan(), Long.class);
//        Result<List<ShuangXiangZZDto>> zhuanZhenJLByIds = reservationCenterAPI.getZhuanZhenJLByIds(ids);
//        if (zhuanZhenJLByIds != null && zhuanZhenJLByIds.isSuccess() && CollectionUtils.isEmpty(zhuanZhenJLByIds.getData())) {
//            throw new CDAException("转诊记录数据不存在", null);
//        }
//        List<ShuangXiangZZDto> shuangXiangZZDtos = zhuanZhenJLByIds.getData();
//        for (ShuangXiangZZDto shuangXiangZZDto : shuangXiangZZDtos) {
//            String xml = zhuanZhenJLApplication.create(shuangXiangZZDto);
//            // 转诊记录里查询病人信息时，appid 使用的是JUYIZHILIAN，因此这里appId也填充相同。
//            validateAndRegister(xml, "JUYIZHILIAN", String.valueOf(shuangXiangZZDto.getBingRenId()));
//        }
//    }

//    private void huiZhenSet(WenDangSCDto wenDangSCDto) throws Exception {
//        List<Long> ids = JSONArray.parseArray(wenDangSCDto.getZiDuan(), Long.class);
//        Result<List<HuiZhenDTO>> huiZhenJLByIds = consultationAPI.getListByIds(ids);
//        if (huiZhenJLByIds != null && huiZhenJLByIds.isSuccess() && CollectionUtils.isEmpty(huiZhenJLByIds.getData())) {
//            throw new CDAException("会诊记录数据不存在", null);
//        }
//        List<HuiZhenDTO> huiZhenDTOS = huiZhenJLByIds.getData();
//        for (HuiZhenDTO huiZhenDTO : huiZhenDTOS) {
//            String xml = huiZhenJLApplication.create(huiZhenDTO);
//            // 会诊记录里查询病人信息时，appid 使用的是huiZhen，因此这里appId也填充相同的、。
//            validateAndRegister(xml, "huiZhen", String.valueOf(huiZhenDTO.getBingRenId()));
//        }
//    }
}
